﻿using GalaSoft.MvvmLight.Command;
using NicoView.Model;
using NicoView.Model.Service;
using NicoView.Model.Service.Broadcast;
using NicoView.Model.Service.Property;
using NicoView.ViewModel.Message;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace NicoView.ViewModel
{
    public class NicoViewBroadcastConsolViewModel:NicoViewViewModelBase
    {

        public NicoViewBroadcastConsolViewModel()
        {
            this.Controllers = new ObservableCollection<NicoViewBroadcastControllerViewModel>();

            this.InternalApplication.Instance.PropertyChanged += OnPropertyChanged;


            this.showBroadcastConsoleCommand = null;

            this.currentController = null;

            this.addControllerCommand = null;

            this.removeControllerCommand = null;

            this.loaded = false;
        }

        private bool loaded;

        private NotificationNicoSelfUser selfUser
        {
            get
            {
                return this.InternalApplication.Instance.SelfUser;
            }
        }


        public bool IsLoggedIn
        {
            get
            {
                return this.selfUser != null;
            }
        }

        public bool IsPremium
        {
            get
            {
                if (!IsLoggedIn) return false;
                return this.selfUser.IsPremium;
            }
        }

        /// <summary>
        /// 現在配信中か判定
        /// </summary>
        public bool IsBroadcasting
        {
            get
            {
                if (this.BroadcastingController == null)
                {
                    return false;
                }
                return this.BroadcastingController.IsBroadcasting;
            }
        }

        public NicoViewBroadcastController BroadcastingController
        {
            get
            {
                return this.InternalApplication.Instance.BroadcastingController;
            }
        }

        #region 通知プロパティ

        private NicoViewBroadcastControllerViewModel currentController;

        public NicoViewBroadcastControllerViewModel CurrentController
        {
            get
            {

                this.prepareReferCurrentController();

                return this.currentController;
            }

            set
            {
                
                if (this.currentController != null)
                {
                    this.currentController.PropertyChanged -= OnPropertyChanged;
                }

                value.PropertyChanged += OnPropertyChanged;

                this.Set(() => this.CurrentController, ref this.currentController, value);
                

                
                
            }

        }

        public ObservableCollection<NicoViewBroadcastControllerViewModel> Controllers { get; private set; }



        #endregion
        
        


        #region コマンド

        private RelayCommand loadCommand;

        public RelayCommand LoadCommand
        {
            get
            {
                if (this.loadCommand == null)
                {
                    this.loadCommand = new RelayCommand(async() =>
                    {
                        await this.LoadAsync();
                    });
                }

                return this.loadCommand;

            }
        }

        private RelayCommand saveCommand;

        public RelayCommand SaveCommand
        {
            get
            {
                if (this.saveCommand == null)
                {
                    this.saveCommand = new RelayCommand(() =>
                    {
                        this.Save();
                    });
                }

                return this.saveCommand;
            }

        }

        private RelayCommand showBroadcastConsoleCommand;

        public RelayCommand ShowBroadcastConsoleCommand
        {
            get
            {
                if (this.showBroadcastConsoleCommand == null)
                {
                    this.showBroadcastConsoleCommand = new RelayCommand(
                    executeShowBroadcasetConsole
                    , canShowBroadcastConsole);


                }

                return this.showBroadcastConsoleCommand;
            }
        }

        private void executeShowBroadcasetConsole()
        {
            this.MessengerInstance.Send(new NicoViewShowBroadcastConsolMessage());
        }


        private bool canShowBroadcastConsole()
        {
            return this.IsPremium && !this.IsBroadcasting;
        }


        private RelayCommand stopBroadcastCommand;

        /// <summary>
        /// Gets the StopBroadcastCommand.
        /// </summary>
        public RelayCommand StopBroadcastCommand
        {
            get
            {
                return stopBroadcastCommand ?? (stopBroadcastCommand = new RelayCommand(
                    executeStopBroadcastCommand,
                    canExecuteStopBroadcastCommand));
            }
        }

        private async void executeStopBroadcastCommand()
        {
            await this.BroadcastingController.StopBroadcastAsync();
            this.MessengerInstance.Send(new NicoViewElapsedTimerStopMessage());
        }

        private bool canExecuteStopBroadcastCommand()
        {
            return this.IsBroadcasting;
        }



        private RelayCommand startBroadcastCommand;
        /// <summary>
        /// Gets the StartBroadcastCommand.
        /// </summary>
        public RelayCommand StartBroadcastCommand
        {
            get
            {
                return startBroadcastCommand ?? (startBroadcastCommand = new RelayCommand(
                    this.executeStartBroadcastCommand,
                    this.canExecuteStartBroadcastCommand));
            }
        }

        private async void executeStartBroadcastCommand()
        {

            this.MessengerInstance.Send(new NicoViewBroadcastStartingMessage());
            var result = await this.CurrentController.Controller.StartBroadcastAsync();

            if (result.Succeed)
            {
                this.MessengerInstance.Send(new NicoViewBroadcastStartedMessage());
            }
            else
            {
                this.MessengerInstance.Send(new NicoViewBroadcastStartFailedMessage(result.Message));
            }

        }

        private bool canExecuteStartBroadcastCommand()
        {
            if (this.CurrentController == null) { return false; }
            var canExecute = this.CurrentController.Title.Length > 0 && this.CurrentController.Description.Length > 0 && this.CurrentController.CurrentCommunityInfo != null && this.CurrentController.PrimaryCategory != LibNiconico.NiconicoApi.Lives.Broadcast.PrimaryCategory.None && (!this.IsBroadcasting);
            return canExecute;
        }


        private ICommand addControllerCommand;

        public ICommand AddControllerCommand
        {
            get
            {
                if (this.addControllerCommand == null)
                {
                    this.addControllerCommand = new RelayCommand(() =>
                    {
                        var newController = new NicoViewBroadcastControllerViewModel();
                        this.Controllers.Add(newController);
                        this.CurrentController = newController;
                    });
                    
                }

                return this.addControllerCommand;
                
            }
        }

        private ICommand removeControllerCommand;

        public ICommand RemoveControllerCommand
        {
            get
            {
                if (this.removeControllerCommand == null)
                {
                    this.removeControllerCommand = new RelayCommand<NicoViewBroadcastControllerViewModel>((parameter) =>
                    {

                        this.remove(parameter);
                    });

                    
                }

                return this.removeControllerCommand;
            }
        }


        

        private RelayCommand<NicoViewBroadcastControllerViewModel> copyControllerCommand;

        /// <summary>
        /// コントローラーをコピー
        /// </summary>
        public RelayCommand<NicoViewBroadcastControllerViewModel> CopyControllerCommand
        {
            get
            {
                return copyControllerCommand
                    ?? (copyControllerCommand = new RelayCommand<NicoViewBroadcastControllerViewModel>(
                                          p =>
                                          {
                                              var newController = new NicoViewBroadcastControllerViewModel((NicoViewBroadcastController)p.Controller.Clone());
                                              this.Controllers.Add(newController);
                                          }));
            }
        }

        private RelayCommand cancelBroadcastCommand;

        /// <summary>
        /// Gets the CancelBroadcastCommand.
        /// </summary>
        public RelayCommand CancelBroadcastCommand
        {
            get
            {
                return cancelBroadcastCommand ?? (cancelBroadcastCommand = new RelayCommand(
                    executeCancelBroadcastCommand));
            }
        }

        private void executeCancelBroadcastCommand()
        {
            this.CurrentController.Controller.EnableRequest = false;

            
        }




        #endregion




        #region メソッド
        private void prepareReferCurrentController()
        {
            
            if (this.Controllers.Count <= 0 && this.loaded)
            {
                this.Controllers.Add(new NicoViewBroadcastControllerViewModel());
            }

                
            
        }


        private void remove(NicoViewBroadcastControllerViewModel parameter)
        {
            if (this.Controllers.Contains(parameter))
            {
                var targetIndex = this.Controllers.IndexOf(parameter);
                this.Controllers.Remove(parameter);

                
            }
        }

        public  void Save()
        {

            this.InternalApplication.Property.BroadcastProperty.Presets.Clear();
            foreach (var controllerViewModell in this.Controllers)
            {
                this.InternalApplication.Property.BroadcastProperty.Presets.Add(controllerViewModell.Controller.Preset);
            }

            if (this.CurrentController != null)
            {
                this.InternalApplication.Property.BroadcastProperty.CurrentPresetId = this.CurrentController.Controller.Preset.PresetId;
            }
            

             
           
        }


        public async Task LoadAsync()
        {

            if (!this.loaded)
            {
                await NicoViewApplication.Current.Property.LoadBroadcastPropertyAsync();



                foreach (var preset in this.InternalApplication.Property.BroadcastProperty.Presets)
                {
                    this.Controllers.Add(new NicoViewBroadcastControllerViewModel(preset));
                }

                var selectController = from controller in this.Controllers
                                       where controller.Controller.Preset.PresetId == this.InternalApplication.Property.BroadcastProperty.CurrentPresetId
                                       select controller;

                if (selectController.Count() > 0)
                {
                    this.CurrentController = selectController.First();
                }
                

                this.RaisePropertyChangedAll();

                this.loaded = true;

                this.prepareReferCurrentController();

            }




        }

        protected override void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(sender, e);

            this.ShowBroadcastConsoleCommand.RaiseCanExecuteChanged();

            this.StopBroadcastCommand.RaiseCanExecuteChanged();

            this.StartBroadcastCommand.RaiseCanExecuteChanged();
        }

        #endregion


    }
}
